package com.chengqs.summer.context;

import com.chengqs.summer.annotation.*;
import com.chengqs.summer.exception.*;
import com.chengqs.summer.io.PropertyResolver;
import com.chengqs.summer.io.ResourceResolver;
import com.chengqs.summer.utils.ClassUtils;
import jakarta.annotation.Nullable;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 这个 AnnotationConfigApplicationContext 类实现了一个基于注解的Bean容器，它提供了以下主要功能：<br>
 *
 * <p>扫描组件：通过 @ComponentScan 和 @Import 扫描配置类中的组件。</p>
 * <p>创建Bean定义：为符合条件的类和方法创建Bean定义。</p>
 * <p>查找Bean定义：提供多种方法根据名字或类型查找Bean定义。</p>
 * <p>处理依赖关系：在Bean定义过程中，支持 @Primary 注解来处理多重候选问题。</p>
 *
 * <p>该类负责扫描指定的包路径中的所有类，识别出符合条件的组件，并将其注册为 Spring 管理的 Bean。
 * 它通过一系列的设计模式来实现其核心功能，包括：
 *
 * <ul>
 *   <li>工厂模式（Factory Pattern）：该类通过反射机制创建和管理 Bean 的实例，而不是通过直接调用构造函数。</li>
 *   <li>单例模式（Singleton Pattern）：Spring 容器默认管理的 Bean 是单例的，确保在整个应用程序中只存在一个实例。</li>
 *   <li>策略模式（Strategy Pattern）：该类可以根据不同的注解策略灵活地处理 Bean 的创建和初始化过程。</li>
 *   <li>模板方法模式（Template Method Pattern）：通过定义组件扫描和 Bean 定义的基本流程，允许子类进行扩展和自定义实现。</li>
 *   <li>责任链模式（Chain of Responsibility Pattern）：在 Bean 定义过程中通过多种检查和处理机制，逐步处理复杂的依赖关系。</li>
 *   <li>观察者模式（Observer Pattern）：在 Bean 生命周期中支持事件机制，通过注解实现特定阶段的初始化和销毁逻辑。</li>
 *   <li>装饰器模式（Decorator Pattern）：通过注解和 AOP 技术动态增强 Bean 的功能，而无需修改其内部结构。</li>
 * </ul>
 */
public class AnnotationConfigApplicationContext {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    // 属性解析器，用于解析配置属性。这在配置Bean时可能需要使用。
    protected final PropertyResolver propertyResolver;
    // 用于存储所有Bean的定义（BeanDefinition），键是Bean的名字，值是对应的Bean定义。
    protected final Map<String, BeanDefinition> beans;

    // 就是定义一个Set<String>跟踪当前正在创建的所有Bean的名称
    private Set<String> creatingBeanNames;

    /**
     * 构造函数，初始化属性解析器，并扫描获取所有Bean的Class类型
     * @param configClass 用来提供配置类，通常标有 @Configuration 注解，用于定义Bean。
     * @param propertyResolver 用于解析配置文件中的属性。
     */
    public AnnotationConfigApplicationContext(Class<?> configClass, PropertyResolver propertyResolver) {
        this.propertyResolver = propertyResolver;
        // 扫描获取所有Bean的Class类型:
        final Set<String> beanClassNames = scanForClassNames(configClass);
        // 创建Bean的定义:
        this.beans = createBeanDefinitions(beanClassNames);

        // 创建BeanName检测循环依赖:
        this.creatingBeanNames = new HashSet<>();

        // 创建@Configuration类型的Bean:
        this.beans.values().stream()
                // 过滤出@Configuration:
                .filter(this::isConfigurationDefinition).sorted().map(def -> {
                    createBeanAsEarlySingleton(def);
                    return def.getName();
                }).collect(Collectors.toList());

        // 创建其他普通Bean:
        createNormalBeans();

        // 通过字段和set方法注入依赖:
        this.beans.values().forEach(def -> {
            injectBean(def);
        });

        // 调用init方法:
        this.beans.values().forEach(def -> {
            initBean(def);
        });
    }

    /**
     * 创建其他普通Bean:
     */
    void createNormalBeans() {
        // 获取BeanDefinition列表:
        List<BeanDefinition> defs = this.beans.values().stream()
                // filter bean definitions by not instantiation:
                .filter(def -> def.getInstance() == null).sorted().collect(Collectors.toList());

        defs.forEach(def -> {
            // 如果Bean未被创建(可能在其他Bean的构造方法注入前被创建):
            if (def.getInstance() == null) {
                // 创建Bean:
                createBeanAsEarlySingleton(def);
            }
        });
    }

    /**
     * 创建一个Bean，但不进行字段和方法级别的注入。如果创建的Bean不是Configuration，则在构造方法中注入的依赖Bean会自动创建。
     * @param def Bean定义
     * @return 创建的Bean实例
     */
    public Object createBeanAsEarlySingleton(BeanDefinition def) {
        logger.atDebug().log("Try create bean '{}' as early singleton: {}", def.getName(), def.getBeanClass().getName());
        if (!this.creatingBeanNames.add(def.getName())) {
            // 检测到重复创建Bean导致的循环依赖:
            throw new UnsatisfiedDependencyException(String.format("创建 bean'%s'时检测到循环依赖", def.getName()));
        }

        // 创建方式：构造方法或工厂方法:
        Executable createFn = null;
        if (def.getFactoryName() == null) {
            // 通过构造方法:
            createFn = def.getConstructor();
        } else {
            // 通过工厂方法:
            createFn = def.getFactoryMethod();
        }

        // 创建参数:
        final Parameter[] parameters = createFn.getParameters();
        final Annotation[][] parametersAnnos = createFn.getParameterAnnotations();
        Object[] args = new Object[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            final Parameter param = parameters[i];
            final Annotation[] paramAnnos = parametersAnnos[i];
            final Value value = ClassUtils.getAnnotation(paramAnnos, Value.class);
            final Autowired autowired = ClassUtils.getAnnotation(paramAnnos, Autowired.class);

            // @Configuration类型的Bean是工厂，不允许使用@Autowired创建:
            final boolean isConfiguration = isConfigurationDefinition(def);
            if (isConfiguration && autowired != null) {
                throw new BeanCreationException(
                        String.format("Cannot specify @Autowired when create @Configuration bean '%s': %s.", def.getName(), def.getBeanClass().getName()));
            }

            // 参数需要@Value或@Autowired两者之一:
            if (value != null && autowired != null) {
                throw new BeanCreationException(
                        String.format("Cannot specify both @Autowired and @Value when create bean '%s': %s.", def.getName(), def.getBeanClass().getName()));
            }
            if (value == null && autowired == null) {
                throw new BeanCreationException(
                        String.format("Must specify @Autowired or @Value when create bean '%s': %s.", def.getName(), def.getBeanClass().getName()));
            }
            // 参数类型:
            final Class<?> type = param.getType();
            if (value != null) {
                // 参数是@Value:
                args[i] = this.propertyResolver.getRequiredProperty(value.value(), type);
            } else {
                // 参数是@Autowired:
                String name = autowired.name();
                boolean required = autowired.value();
                // 依赖的BeanDefinition:
                BeanDefinition dependsOnDef = name.isEmpty() ? findBeanDefinition(type) : findBeanDefinition(name, type);
                // 检测required==true?
                if (required && dependsOnDef == null) {
                    throw new BeanCreationException(String.format("Missing autowired bean with type '%s' when create bean '%s': %s.", type.getName(),
                            def.getName(), def.getBeanClass().getName()));
                }
                if (dependsOnDef != null) {
                    // 获取依赖Bean:
                    Object autowiredBeanInstance = dependsOnDef.getInstance();
                    if (autowiredBeanInstance == null && !isConfiguration) {
                        // 当前依赖Bean尚未初始化，递归调用初始化该依赖Bean:
                        autowiredBeanInstance = createBeanAsEarlySingleton(dependsOnDef);
                    }
                    args[i] = autowiredBeanInstance;
                } else {
                    args[i] = null;
                }
            }
        }

        // 创建Bean实例:
        Object instance = null;
        if (def.getFactoryName() == null) {
            // 用构造方法创建:
            try {
                instance = def.getConstructor().newInstance(args);
            } catch (Exception e) {
                throw new BeanCreationException(String.format("Exception when create bean '%s': %s", def.getName(), def.getBeanClass().getName()), e);
            }
        } else {
            // 用@Bean方法创建:
            Object configInstance = getBean(def.getFactoryName());
            try {
                instance = def.getFactoryMethod().invoke(configInstance, args);
            } catch (Exception e) {
                throw new BeanCreationException(String.format("Exception when create bean '%s': %s", def.getName(), def.getBeanClass().getName()), e);
            }
        }
        def.setInstance(instance);
        return def.getInstance();
    }

    /**
     * 根据扫描的ClassName创建BeanDefinition
     * @param classNameSet 从 scanForClassNames 方法获取到的所有Class名。
     * @return 返回一个Map，其中包含了所有的Bean定义。
     */
    Map<String, BeanDefinition> createBeanDefinitions(Set<String> classNameSet) {
        // 创建一个map集合存储Bean定义
        Map<String, BeanDefinition> defs = new HashMap<>();
        for (String className : classNameSet) {
            // 遍历每一个Class名，尝试加载Class对象。
            Class<?> clazz = null;
            try {
                clazz = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new BeanCreationException(e);
            }
            if (clazz.isAnnotation() || clazz.isEnum() || clazz.isInterface() || clazz.isRecord()) {
                // 跳过注解类型、枚举类型、接口以及Java 14引入的记录类型。
                continue;
            }
            // 如果一个类标注了 @Component 注解，则尝试创建一个 BeanDefinition。
            Component component = ClassUtils.findAnnotation(clazz, Component.class);
            if (component != null) {
                logger.atDebug().log("found component: {}", clazz.getName());
                // 获取类的权限修饰符
                int mod = clazz.getModifiers();
                if (Modifier.isAbstract(mod)) {
                    // 如果是抽象类，则抛出异常
                    throw new BeanDefinitionException("@Component class " + clazz.getName() + " must not be abstract.");
                }
                if (Modifier.isPrivate(mod)) {
                    // 如果是私有类，则抛出异常
                    throw new BeanDefinitionException("@Component class " + clazz.getName() + " must not be private.");
                }

                // 获取Bean的名字
                String beanName = ClassUtils.getBeanName(clazz);
                // 创建 BeanDefinition:
                BeanDefinition def = new BeanDefinition(
                        beanName,
                        clazz,
                        // 获取合适的构造函数
                        getSuitableConstructor(clazz),
                        // 获取Bean的顺序
                        getOrder(clazz),
                        // 检查是否有 @Primary 注解。
                        clazz.isAnnotationPresent(Primary.class),
                        // named init
                        null,
                        // destroy method:
                        null,
                        // 获取初始化方法
                        ClassUtils.findAnnotationMethod(clazz, PostConstruct.class),
                        // 获取销毁方法
                        ClassUtils.findAnnotationMethod(clazz, PreDestroy.class));
                addBeanDefinitions(defs, def);
                logger.atDebug().log("define bean: {}", def);

                // 如果类有 @Configuration 注解，则调用 scanFactoryMethods 方法，扫描工厂方法（带 @Bean 注解的方法）。
                Configuration configuration = ClassUtils.findAnnotation(clazz, Configuration.class);
                if (configuration != null) {
                    scanFactoryMethods(beanName, clazz, defs);
                }
            }
        }
        return defs;
    }

    /**
     * 注入依赖但不调用init方法
     * @param def Bean定义
     */
    void injectBean(BeanDefinition def) {
        try {
            injectProperties(def, def.getBeanClass(), def.getInstance());
        } catch (ReflectiveOperationException e) {
            throw new BeanCreationException(e);
        }
    }

    /**
     * 调用init方法
     * @param def Bean定义
     */
    void initBean(BeanDefinition def) {
        // 调用init方法:
        callMethod(def.getInstance(), def.getInitMethod(), def.getInitMethodName());
    }

    /**
     * 注入属性
     * @param def Bean定义
     * @param clazz Bean的声明类型
     * @param bean Bean的实例
     * @throws ReflectiveOperationException 异常
     */
    void injectProperties(BeanDefinition def, Class<?> clazz, Object bean) throws ReflectiveOperationException {
        // 在当前类查找Field和Method并注入:
        for (Field f : clazz.getDeclaredFields()) {
            tryInjectProperties(def, clazz, bean, f);
        }
        for (Method m : clazz.getDeclaredMethods()) {
            tryInjectProperties(def, clazz, bean, m);
        }
        // 在父类查找Field和Method并注入:
        Class<?> superClazz = clazz.getSuperclass();
        if (superClazz != null) {
            injectProperties(def, superClazz, bean);
        }
    }

    /**
     * 尝试向Bean的字段或方法注入属性。
     * <p>
     * 该方法通过反射机制，向指定的字段或方法注入属性值。属性值可以通过`@Value`注解直接从配置中获取，
     * 或通过`@Autowired`注解从Spring容器中获取其他Bean的实例。
     * </p>
     *
     * @param def   BeanDefinition对象，包含Bean的定义信息
     * @param clazz Bean的Class对象，表示Bean的类型
     * @param bean  要进行注入的Bean实例
     * @param acc   AccessibleObject对象，可以是字段或方法，用于注入
     * @throws ReflectiveOperationException 当反射操作失败时抛出异常
     */
    void tryInjectProperties(BeanDefinition def, Class<?> clazz, Object bean, AccessibleObject acc) throws ReflectiveOperationException {
        // 获取字段或方法上的@Value注解和@Autowired注解
        Value value = acc.getAnnotation(Value.class);
        Autowired autowired = acc.getAnnotation(Autowired.class);
        // 如果没有注解，则无需注入，直接返回
        if (value == null && autowired == null) {
            return;
        }
        // 用于存储待注入的Field或Method
        Field field = null;
        Method method = null;
        // 检查acc是否为Field实例，并进行相关处理
        if (acc instanceof Field f) {
            // 检查字段是否符合注入要求
            checkFieldOrMethod(f);
            // 设置字段为可访问（包括私有字段）
            f.setAccessible(true);
            field = f; // 将字段对象存储到field变量中
        }
        // 检查acc是否为Method实例，并进行相关处理
        if (acc instanceof Method m) {
            // 检查方法是否符合注入要求
            checkFieldOrMethod(m);
            // 验证方法是否为setter方法（参数个数必须为1）
            if (m.getParameters().length != 1) {
                throw new BeanDefinitionException(
                        String.format("Cannot inject a non-setter method %s for bean '%s': %s", m.getName(), def.getName(), def.getBeanClass().getName()));
            }
            // 设置方法为可访问（包括私有方法）
            m.setAccessible(true);
            method = m; // 将方法对象存储到method变量中
        }

        // 确定待注入的成员名和类型
        String accessibleName = field != null ? field.getName() : method.getName(); // 字段名或方法名
        Class<?> accessibleType = field != null ? field.getType() : method.getParameterTypes()[0]; // 字段类型或方法参数类型

        // 检查是否同时存在@Value和@Autowired注解，若存在则抛出异常
        if (value != null && autowired != null) {
            throw new BeanCreationException(String.format("Cannot specify both @Autowired and @Value when inject %s.%s for bean '%s': %s",
                    clazz.getSimpleName(), accessibleName, def.getName(), def.getBeanClass().getName()));
        }

        // 处理@Value注解的注入
        if (value != null) {
            // 获取@Value指定的属性值并进行类型转换
            Object propValue = this.propertyResolver.getRequiredProperty(value.value(), accessibleType);
            // 根据注解所在位置（字段或方法）进行相应的注入操作
            if (field != null) {
                // 注入到字段
                logger.atDebug().log("Field injection: {}.{} = {}", def.getBeanClass().getName(), accessibleName, propValue);
                field.set(bean, propValue);
            }
            if (method != null) {
                // 注入到方法
                logger.atDebug().log("Method injection: {}.{} ({})", def.getBeanClass().getName(), accessibleName, propValue);
                method.invoke(bean, propValue);
            }
        }

        // 处理@Autowired注解的注入
        if (autowired != null) {
            // 获取@Autowired注解的参数
            String name = autowired.name(); // 依赖的Bean名称
            boolean required = autowired.value(); // 是否为必需

            // 根据名称或类型查找依赖的Bean实例
            Object depends = name.isEmpty() ? findBean(accessibleType) : findBean(name, accessibleType);
            if (required && depends == null) {
                // 如果依赖的Bean是必需的且未找到，则抛出异常
                throw new UnsatisfiedDependencyException(String.format("Dependency bean not found when inject %s.%s for bean '%s': %s", clazz.getSimpleName(),
                        accessibleName, def.getName(), def.getBeanClass().getName()));
            }
            // 如果找到了依赖的Bean实例，则进行注入
            if (depends != null) {
                if (field != null) {
                    // 注入到字段
                    logger.atDebug().log("Field injection: {}.{} = {}", def.getBeanClass().getName(), accessibleName, depends);
                    field.set(bean, depends);
                }
                if (method != null) {
                    // 注入到方法
                    logger.atDebug().log("Mield injection: {}.{} ({})", def.getBeanClass().getName(), accessibleName, depends);
                    method.invoke(bean, depends);
                }
            }
        }
    }

    /**
     * 检查Field或Method是否是静态、最终的。
     * @param m Field或Method
     */
    void checkFieldOrMethod(Member m) {
        int mod = m.getModifiers();
        if (Modifier.isStatic(mod)) {
            throw new BeanDefinitionException("Cannot inject static field: " + m);
        }
        if (Modifier.isFinal(mod)) {
            if (m instanceof Field field) {
                throw new BeanDefinitionException("Cannot inject final field: " + field);
            }
            if (m instanceof Method method) {
                logger.warn(
                        "Inject final method should be careful because it is not called on target bean when bean is proxied and may cause NullPointerException.");
            }
        }
    }

    /**
     * 获取公共构造函数或非公共构造函数作为后备。
     * @param clazz 类对象，用于获取其构造函数。
     * @return 返回找到的构造函数。
     */
    Constructor<?> getSuitableConstructor(Class<?> clazz) {
        // 获取所有公共构造函数
        Constructor<?>[] cons = clazz.getConstructors();
        if (cons.length == 0) {
            // 如果没有公共构造函数，则获取所有构造函数
            cons = clazz.getDeclaredConstructors();
            if (cons.length != 1) {
                // 如果找到的构造函数不唯一，则抛出异常。
                throw new BeanDefinitionException("More than one constructor found in class " + clazz.getName() + ".");
            }
        }
        if (cons.length != 1) {
            // 如果类有多个公共构造函数，则抛出异常。
            throw new BeanDefinitionException("More than one public constructor found in class " + clazz.getName() + ".");
        }
        // 返回构造函数
        return cons[0];
    }

    /**
     * 扫描类中所有方法，查找带有 @Bean 注解的方法。
     * @param factoryBeanName 工厂Bean的名称，用于在Bean定义中标记创建此Bean的工厂类。
     * @param clazz 需要扫描的配置类，用于查找带 @Bean 注解的方法。
     * @param defs 存储Bean定义的Map。
     */
    void scanFactoryMethods(String factoryBeanName, Class<?> clazz, Map<String, BeanDefinition> defs) {
        // 获取所有方法
        for (Method method : clazz.getDeclaredMethods()) {
            // 获取 @Bean 注解
            Bean bean = method.getAnnotation(Bean.class);
            if (bean != null) {
                // 获取权限修饰符
                int mod = method.getModifiers();
                if (Modifier.isAbstract(mod)) {
                    // 如果是抽象方法，则抛出异常
                    throw new BeanDefinitionException("@Bean method " + clazz.getName() + "." + method.getName() + " must not be abstract.");
                }
                if (Modifier.isFinal(mod)) {
                    // 如果是final方法，则抛出异常
                    throw new BeanDefinitionException("@Bean method " + clazz.getName() + "." + method.getName() + " must not be final.");
                }
                if (Modifier.isPrivate(mod)) {
                    // 如果是私有方法，则抛出异常
                    throw new BeanDefinitionException("@Bean method " + clazz.getName() + "." + method.getName() + " must not be private.");
                }
                // 获取返回值类型
                Class<?> beanClass = method.getReturnType();
                if (beanClass.isPrimitive()) {
                    // 如果返回值是基本类型，则抛出异常。
                    throw new BeanDefinitionException("@Bean method " + clazz.getName() + "." + method.getName() + " must not return primitive type.");
                }
                if (beanClass == void.class || beanClass == Void.class) {
                    // 如果返回值是void，则抛出异常。
                    throw new BeanDefinitionException("@Bean method " + clazz.getName() + "." + method.getName() + " must not return void.");
                }
                BeanDefinition def = new BeanDefinition(
                        ClassUtils.getBeanName(method),
                        beanClass,
                        factoryBeanName,
                        method,
                        getOrder(method),
                        method.isAnnotationPresent(Primary.class),
                        // 获取初始化方法:
                        bean.initMethod().isEmpty() ? null : bean.initMethod(),
                        // 获取销毁方法
                        bean.destroyMethod().isEmpty() ? null : bean.destroyMethod(),
                        // @PostConstruct / @PreDestroy method:
                        null, null);
                // 加入到Bean定义的Map中
                addBeanDefinitions(defs, def);
                logger.atDebug().log("define bean: {}", def);
            }
        }
    }

    /**
     * 将Bean定义添加到Map中。
     * @param defs 存储Bean定义的Map。
     * @param def 待添加的Bean定义。
     */
    void addBeanDefinitions(Map<String, BeanDefinition> defs, BeanDefinition def) {
        if (defs.put(def.getName(), def) != null) {
            // 如果存在重复的Bean名，则抛出 BeanDefinitionException 异常。
            throw new BeanDefinitionException("Duplicate bean name: " + def.getName());
        }
    }

    /**
     * 获取类的顺序值，如果没有标注 @Order 注解，则返回默认的最大值。
     * @param clazz 用于获取其上的 @Order 注解。
     * @return 返回顺序值。
     */
    int getOrder(Class<?> clazz) {
        Order order = clazz.getAnnotation(Order.class);
        return order == null ? Integer.MAX_VALUE : order.value();
    }

    /**
     * 获取方法的顺序值，如果没有标注 @Order 注解，则返回默认的最大值。
     * @param method 方法对象，用于获取其上的 @Order 注解。
     * @return 返回顺序值。
     */
    int getOrder(Method method) {
        Order order = method.getAnnotation(Order.class);
        return order == null ? Integer.MAX_VALUE : order.value();
    }

    /**
     * 扫描配置类中的所有Class名。
     * @param configClass 配置类，用于扫描组件的包名。
     * @return 返回扫描到的Class名。
     */
    protected Set<String> scanForClassNames(Class<?> configClass) {
        // 获取ComponentScan注解
        ComponentScan scan = ClassUtils.findAnnotation(configClass, ComponentScan.class);
        // 获取包名
        // ComponentScan为null或这个属性为空，则使用配置类的包名。
        final String[] scanPackages = scan == null || scan.value().length == 0 ? new String[] { configClass.getPackage().getName() } : scan.value();
        logger.atInfo().log("component scan in packages: {}", Arrays.toString(scanPackages));

        // 创建类名集合
        Set<String> classNameSet = new HashSet<>();
        for (String pkg : scanPackages) {
            // 扫描package:
            logger.atDebug().log("scan package: {}", pkg);
            // 构造资源解析器
            ResourceResolver rr = new ResourceResolver(pkg);
            // 获取所有类的名字
            List<String> classList = rr.scan(res -> {
                String name = res.name();
                if (name.endsWith(".class")) {
                    return name.substring(0, name.length() - 6).replace("/", ".").replace("\\", ".");
                }
                return null;
            });
            if (logger.isDebugEnabled()) {
                classList.forEach((className) -> {
                    logger.debug("class found by component scan: {}", className);
                });
            }
            // 添加到集合中
            classNameSet.addAll(classList);
        }

        // 查找@Import(Xyz.class):
        Import importConfig = configClass.getAnnotation(Import.class);
        if (importConfig != null) {
            for (Class<?> importConfigClass : importConfig.value()) {
                // 遍历并获取类名
                String importClassName = importConfigClass.getName();
                if (classNameSet.contains(importClassName)) {
                    logger.warn("ignore import: " + importClassName + " for it is already been scanned.");
                } else {
                    logger.debug("class found by import: {}", importClassName);
                    classNameSet.add(importClassName);
                }
            }
        }
        return classNameSet;
    }

    /**
     * 判断一个Bean定义是否是一个配置类，即检查其上是否标注了 @Configuration 注解。
     * @param def Bean定义。
     * @return 返回是否是一个配置类。
     */
    boolean isConfigurationDefinition(BeanDefinition def) {
        return ClassUtils.findAnnotation(def.getBeanClass(), Configuration.class) != null;
    }

    /**
     * 根据Name查找BeanDefinition，如果Name不存在，返回null
     * @param name Bean的名字。
     * @return 返回BeanDefinition。
     */
    @Nullable
    public BeanDefinition findBeanDefinition(String name) {
        return this.beans.get(name);
    }

    /**
     * 根据Name和Type查找BeanDefinition，如果Name不存在，返回null，如果Name存在，但Type不匹配，抛出异常。
     * @param name Bean的名字。
     * @param requiredType 所需的类型。
     * @return 返回BeanDefinition。
     */
    @Nullable
    public BeanDefinition findBeanDefinition(String name, Class<?> requiredType) {
        BeanDefinition def = findBeanDefinition(name);
        if (def == null) {
            return null;
        }
        if (!requiredType.isAssignableFrom(def.getBeanClass())) {
            throw new BeanNotOfRequiredTypeException(String.format("Autowire required type '%s' but bean '%s' has actual type '%s'.", requiredType.getName(),
                    name, def.getBeanClass().getName()));
        }
        return def;
    }

    /**
     * 根据Type查找若干个BeanDefinition，返回0个或多个。
     * @param type 所需的类型。
     * @return 返回BeanDefinition列表。
     */
    public List<BeanDefinition> findBeanDefinitions(Class<?> type) {
        return this.beans.values().stream()
                // filter by type and sub-type:
                .filter(def -> type.isAssignableFrom(def.getBeanClass()))
                // 排序:
                .sorted().collect(Collectors.toList());
    }

    /**
     * 根据Type查找某个BeanDefinition，如果不存在返回null，如果存在多个返回@Primary标注的一个，
     * 如果有多个@Primary标注，或没有@Primary标注但找到多个，均抛出NoUniqueBeanDefinitionException
     * @param type 所需的类型。
     * @return 返回BeanDefinition。
     */
    @Nullable
    public BeanDefinition findBeanDefinition(Class<?> type) {
        // 查找符合给定类型的Bean定义。
        List<BeanDefinition> defs = findBeanDefinitions(type);
        if (defs.isEmpty()) {
            // 如果不存在返回 null。
            return null;
        }
        if (defs.size() == 1) {
            // 如果存在一个，返回该Bean定义。
            return defs.get(0);
        }
        // 如果存在多个，查找 @Primary 注解的Bean定义。
        List<BeanDefinition> primaryDefs = defs.stream().filter(def -> def.isPrimary()).collect(Collectors.toList());
        if (primaryDefs.size() == 1) {
            return primaryDefs.get(0);
        }
        // 如果有多个 @Primary 注解或没有 @Primary 注解但找到多个Bean定义，抛出 NoUniqueBeanDefinitionException。
        if (primaryDefs.isEmpty()) {
            throw new NoUniqueBeanDefinitionException(String.format("Multiple bean with type '%s' found, but no @Primary specified.", type.getName()));
        } else {
            throw new NoUniqueBeanDefinitionException(String.format("Multiple bean with type '%s' found, and multiple @Primary specified.", type.getName()));
        }
    }

    /**
     * 通过Name查找Bean，不存在时抛出NoSuchBeanDefinitionException
     */
    @SuppressWarnings("unchecked")
    public <T> T getBean(String name) {
        BeanDefinition def = this.beans.get(name);
        if (def == null) {
            throw new NoSuchBeanDefinitionException(String.format("No bean defined with name '%s'.", name));
        }
        return (T) def.getRequiredInstance();
    }

    /**
     * 通过Name和Type查找Bean，不存在抛出NoSuchBeanDefinitionException，存在但与Type不匹配抛出BeanNotOfRequiredTypeException
     */
    public <T> T getBean(String name, Class<T> requiredType) {
        T t = findBean(name, requiredType);
        if (t == null) {
            throw new NoSuchBeanDefinitionException(String.format("No bean defined with name '%s' and type '%s'.", name, requiredType));
        }
        return t;
    }

    /**
     * 通过Type查找Beans
     */
    @SuppressWarnings("unchecked")
    public <T> List<T> getBeans(Class<T> requiredType) {
        List<BeanDefinition> defs = findBeanDefinitions(requiredType);
        if (defs.isEmpty()) {
            return List.of();
        }
        List<T> list = new ArrayList<>(defs.size());
        for (var def : defs) {
            list.add((T) def.getRequiredInstance());
        }
        return list;
    }

    /**
     * 通过Type查找Bean，不存在抛出NoSuchBeanDefinitionException，存在多个但缺少唯一@Primary标注抛出NoUniqueBeanDefinitionException
     */
    @SuppressWarnings("unchecked")
    public <T> T getBean(Class<T> requiredType) {
        BeanDefinition def = findBeanDefinition(requiredType);
        if (def == null) {
            throw new NoSuchBeanDefinitionException(String.format("No bean defined with type '%s'.", requiredType));
        }
        return (T) def.getRequiredInstance();
    }

    /**
     * 检测是否存在指定Name的Bean
     */
    public boolean containsBean(String name) {
        return this.beans.containsKey(name);
    }

    // findXxx与getXxx类似，但不存在时返回null

    @Nullable
    @SuppressWarnings("unchecked")
    protected <T> T findBean(String name, Class<T> requiredType) {
        BeanDefinition def = findBeanDefinition(name, requiredType);
        if (def == null) {
            return null;
        }
        return (T) def.getRequiredInstance();
    }

    @Nullable
    @SuppressWarnings("unchecked")
    protected <T> T findBean(Class<T> requiredType) {
        BeanDefinition def = findBeanDefinition(requiredType);
        if (def == null) {
            return null;
        }
        return (T) def.getRequiredInstance();
    }

    @Nullable
    @SuppressWarnings("unchecked")
    protected <T> List<T> findBeans(Class<T> requiredType) {
        return findBeanDefinitions(requiredType).stream().map(def -> (T) def.getRequiredInstance()).collect(Collectors.toList());
    }

    /**
     * 调用指定的初始化或销毁方法。
     *
     * 在Bean的生命周期中，当Bean完成初始化或即将销毁时，可能需要执行一些自定义的逻辑。
     * 此方法用于调用这些自定义方法，可以通过直接传入Method对象或方法名称进行调用。
     *
     * @param beanInstance 要调用方法的Bean实例
     * @param method       Method对象，表示要调用的初始化或销毁方法；如果为null，则使用namedMethod查找
     * @param namedMethod  方法名称，用于在beanInstance的类中查找要调用的方法；当method为null时有效
     */
    private void callMethod(Object beanInstance, Method method, String namedMethod) {
        // 调用通过Method对象传入的方法（如果存在）
        if (method != null) {
            try {
                // 使用反射调用方法，beanInstance作为调用对象
                method.invoke(beanInstance);
            } catch (ReflectiveOperationException e) {
                // 捕获反射操作异常并转换为BeanCreationException
                throw new BeanCreationException(e);
            }
        } else if (namedMethod != null) {
            // 如果Method对象为null，且指定了方法名称，则通过名称查找方法
            // 注意：查找是在beanInstance的实际类型中进行的
            Method named = ClassUtils.getNamedMethod(beanInstance.getClass(), namedMethod);
            // 将方法设置为可访问（包括私有方法）
            named.setAccessible(true);
            try {
                // 使用反射调用找到的方法，beanInstance作为调用对象
                named.invoke(beanInstance);
            } catch (ReflectiveOperationException e) {
                // 捕获反射操作异常并转换为BeanCreationException
                throw new BeanCreationException(e);
            }
        }
    }

}
